//ThreadPool.hpp
#pragma once
#include <iostream>
#include <unistd.h>
#include <vector>
#include <pthread.h>
#include "Task.hpp"
#include <queue>
#include "Thread.hpp"
#include "Lock.hpp"
#define SIZE 5
using namespace std;
template <class T=Task>
class ThreadPool
{
    //单例模式
private:
    ThreadPool(int num = SIZE)
        : _capacity(num)
    {
        pthread_cond_init(&_cond, nullptr);
        pthread_mutex_init(&_mutex, nullptr);
    }

    ThreadPool(ThreadPool<T> &t) = delete;
    ThreadPool<T> &operator=(ThreadPool<T> &t) = delete;

public:
    static ThreadPool<T> *GetInstance()
    {
        //double-check，提高效率
        if (_ptr == nullptr)
        {
            MutexGuard Lock(&_instance_mutex);
            if (_ptr == nullptr)
            {
                _ptr = new ThreadPool<T>;
                _ptr->Init();
                _ptr->start();
            }
        }
        return _ptr;
    }

    //析构函数
    ~ThreadPool()
    {
        for (int i = 0; i < _capacity; i++)
        {
            _pool[i].join();
        }

        pthread_cond_destroy(&_cond);
        pthread_mutex_destroy(&_mutex);
    }

    //线程池的初始化
    void Init()
    {
        //完成线程池的创建
        for (int i = 0; i < _capacity; i++)
        {
            _pool.push_back(Thread(i, pthreadRoutine, this));
        }
    }

    //线程池任务是否为空
    bool IsEmpty()
    {
        return _task.empty();
    }

    //条件变量等待
    void PthreadCondWait()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }

    //获取任务
    T popTask()
    {
        T t = _task.front();
        _task.pop();
        return t;
    }

    //获取锁
    pthread_mutex_t *PthreadLock()
    {
        return &_mutex;
    }
    
    //这边的逻辑：ThreadPool中Init时把线程"创建"好并把执行task的pthreadRoutinue传过去，
    //在Start中正式创建线程并运行，线程执行pthreadRoutinue，pthreadRoutinue中再执行task
    //task中会再执行服务器的Service
    static void pthreadRoutine(void *arg)
    {
        ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(arg);
        while (true)
        {
            T task;
            {
                MutexGuard m(tp->PthreadLock());
                while (tp->IsEmpty())//防止虚假唤醒，因为万一代码中哪里写了唤醒，但是实际并没有task
                {
                    tp->PthreadCondWait();
                }
                task = tp->popTask();
            }
            task();
        }
    }

    //线程真正开始运行
    void start()
    {
        for (int i = 0; i < _capacity; i++)
        {
            _pool[i].Run();
        }
    }

    //查看线程
    void Check()
    {
        for (auto &e : _pool)
        {
            cout << e.name() << endl;
        }
    }

    //给线程池增加任务
    void push(const T &task)
    {
        MutexGuard m(&_mutex);
        _task.push(task);
        pthread_cond_signal(&_cond);
    }

private:
    vector<Thread> _pool;
    queue<T> _task;
    int _capacity;
    pthread_cond_t _cond;
    pthread_mutex_t _mutex;
    static ThreadPool<T> *_ptr;
    static pthread_mutex_t _instance_mutex;
};

template <class T>
ThreadPool<T> *ThreadPool<T>::_ptr = nullptr;
template <class T>
pthread_mutex_t ThreadPool<T>::_instance_mutex=PTHREAD_MUTEX_INITIALIZER;